// provide() 和 inject() 总结：
// 可以实现嵌套组件之间的数据传递。
// 这两个函数只能在 setup() 函数中使用。
// 父级组件中使用 provide() 函数向下传递数据。provide("data", data);
// 子级组件中使用 inject() 获取上层传递过来的数据。
// provide() 和 inject() 定义格式：
// function provide<T>(key: InjectionKey<T> | string, value: T): void
// function inject<T>(key: InjectionKey<T> | string): T | undefined
import { designComponent } from 'src/use/designComponent'
import {
  reactive,
  onBeforeUnmount,
  getCurrentInstance
} from 'vue'

// 声明路由接口
interface Route {
  path?: string
  hash?: string
  param?: { [k: string]: string }
}

// 定义一个常量字符串，作为key
// const APP_NAVIGATOR_PROVIDER = '@@app-navigator'

/**
 * hash路由
 * @author  mao
 */
function getRoute(): Route {
  let locationHash = window.location.hash || ''
  if (locationHash.charAt(0) === '#') {
    locationHash = locationHash.slice(1)
  }
  const [path, hash] = decodeURIComponent(locationHash).split('#')
  return {
    path,
    hash
  }
}

/**
 *
 * @param props 从父组件中传过来的数据，包含默认路由地址
 */
// function useAppNavigator(props: { defaultPath?: string }) {
//   const currentRoute = getRoute()
//   !currentRoute.path && (currentRoute.path = props.defaultPath)

//   const state = reactive({
//     route: currentRoute
//   })

//   const methods = {
//     go(path: string) {
//       window.location.hash = encodeURIComponent(path)
//     }
//   }

//   const handler = {
//     hashchange: () => {
//       state.route = getRoute()
//     }
//   }

//   const refer = {
//     state,
//     methods
//   }

//   const ctx = getCurrentInstance()

//     ; (ctx as any)._refer = refer
//   window.addEventListener('hashchange', handler.hashchange)
//   onBeforeUnmount(() =>
//     window.removeEventListener('hashchange', handler.hashchange)
//   )

//   // 将数据提供给子组件使用  provide("data", data);
//   provide(APP_NAVIGATOR_PROVIDER, refer)

//   return refer
// }

// 该方法在子组件中调用，将父组件中数据，传递给子组件
// export function injectAppNavigator() {
//   return inject(APP_NAVIGATOR_PROVIDER) as ReturnType<typeof useAppNavigator>
// }

// app-navigator
// export const AppNavigator = defineComponent({
//   name: 'app-navigator',
//   props: {
//     defaultPath: String
//   },
//   setup(props, setupContext) {
//     useAppNavigator(props)

//     return () =>
//       !!setupContext.slots.default ? setupContext.slots.default() : null
//   }
// })


export const AppNavigator = designComponent({
  name: 'app-navigator',
  props: {
    defaultPath: String
  },
  provideRefer: true,
  setup({ props, setupContext}) {
    const currentRoute = getRoute()
    !currentRoute.path && (currentRoute.path = props.defaultPath)

    const state = reactive({
      route: currentRoute
    })

    const methods = {
      go(path: string) {
        window.location.hash = encodeURIComponent(path)
      }
    }

    const handler = {
      hashchange: () => {
        state.route = getRoute()
      }
    }

    const refer = {
      state,
      methods
    }

    const ctx = getCurrentInstance()

      ; (ctx as any)._refer = refer
    window.addEventListener('hashchange', handler.hashchange)
    onBeforeUnmount(() =>
      window.removeEventListener('hashchange', handler.hashchange)
    )

    return {
      refer,
      render: () =>
        !!setupContext.slots.default ? setupContext.slots.default() : null
    }
  }
})